﻿#region Using References

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;

#endregion

namespace Beaker.OpenCube.NbtEditor.ViewModels
{
	public abstract class ViewModel
		: ViewModelBase
	{
		/// <summary>
		/// Sets the value of the property and raise NotifyPropertyChanged if changed.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="backingStore">The backing store that holds the value.</param>
		/// <param name="newValue">The new value to set to.</param>
		/// <param name="onChange">The action callback to call if the value actually has changed.</param>
		/// <param name="propertyName">Name of the property.</param>
		protected void SetAndRaiseIfChanged<T>( ref T backingStore, T newValue, Action<T, T> onChange = null, [CallerMemberName] string propertyName = null )
		{
			Contract.Requires<ArgumentNullException>( propertyName != null, "A property name is required" );
			Contract.Ensures( backingStore.Equals( newValue ) );

			bool hasChanged = !EqualityComparer<T>.Default.Equals( backingStore, newValue );
			if( hasChanged )
			{
				T oldValue = backingStore;

				RaisePropertyChanging( propertyName );
				backingStore = newValue;
				RaisePropertyChanged( propertyName );

				if( onChange != null )
					onChange( oldValue, newValue );
			}
		}

		/// <summary>
		/// Sends the specified message.
		/// </summary>
		/// <param name="message">The message to send.</param>
		protected void Send<TMessage>( TMessage message )
			where TMessage : MessageBase
		{
			Contract.Requires<ArgumentNullException>( message != null, "A message is required" );
			Messenger.Default.Send( message );
		}
	}
}
